"""@author: sarjanshrestha"""

import collections
import numpy as np
import itertools



def is_number(s):
    try:
        float(s)
        return True
    except ValueError:
        return False
    
def continuous_Prob(x,m,s):
    result=round(np.exp(-np.square(x-m)/2*np.square(s)))/np.sqrt(2*np.pi*np.square(s))
    return result

f=open('c:\python27\kddcup.data_10_percent.txt','r') 

f.seek(0)

columns=collections.defaultdict(int)
probClass=collections.defaultdict(int)
jointCount=collections.defaultdict(int)
jointProbClass=collections.defaultdict(int)
classAttribute=[]
predictCounts=collections.defaultdict(int)
predictClass=collections.defaultdict(int)
predictResult={}
data=[]
coln=[]
mu=[]
sd=[]
maxm=[]



for line in f:
    vL=len(line.split(','))                 #count the number of columns in table
    break



f.seek(0)
for line in f:
    data.append(line.strip().strip('\n').split(','))

f.close()
    
for rows in data:
    for counter in range(len(rows)):
        if is_number(rows[counter]) and (counter not in coln):
            coln.append(counter)                                        #find the number of columns with continous values

        if (rows[len(rows)-1]) not in classAttribute:                   #get the number of classes to predict the given instance
                classAttribute.append((rows[len(rows)-1]))


data1=[]
data2=[]
 
for line in data:
    if (line[len(line)-1]=='normal.'):
        data1.append(line)
    else:
        data2.append(line)
        
nCount=len(data1)                   #total number of normal event counts
aCount=len(data2)                   #total number of anomaly event counts

probN=np.float64(nCount)/np.float64(len(data))     #probability of normal events
probA=np.float64(aCount)/np.float64(len(data))      #probability of anomaly events


arrN=np.array(data1)
arrA=np.array(data2)


arrN1=np.zeros((len(data1),len(coln)))


for rows,j in itertools.izip(arrN,range(len(arrN))):                           # get array of numbers from data1
    for count,i in itertools.izip(coln,range(len(coln))):
        arrN1[j][i]=rows[count]
        
for i in range(len(coln)):                                                  #avoid zero probability
    if np.sum(arrN1[:,i])==0:
        arrN1[1][i]=1



   
arrA1=np.zeros((len(data2),len(coln)))
        
for rows,j in itertools.izip(arrA,range(len(arrA))):                           # get array of numbers from data2
    for count,i in itertools.izip(coln,range(len(coln))):
        arrA1[j][i]=rows[count]
       

for i in range(len(coln)):                                                  #avoid zero probability
    if np.sum(arrA1[:,i])==0:
        arrA1[1][i]=1        

muN=np.zeros((len(coln)))
stdN=np.zeros((len(coln)))


for dv in arrN1:
    for count in range(len(dv)):
        muN[count]=np.mean(arrN1[:,count])
        stdN[count]=np.std(arrN1[:,count])
    break

muA=np.zeros((len(coln)))
stdA=np.zeros((len(coln)))

      
for dv in arrA1:
    for count in range(len(dv)):
        muA[count]=np.mean(arrA1[:,count])
        stdA[count]=np.std(arrA1[:,count])
    break

for i in range(len(coln)):
    if stdN[i]==0:
        print stdN[i]
for j in range(len(coln)):
    if stdA[i]==0:
        print stdA[j]



# arrN=np.zeros((len(data1),len(coln))) 
# arrA=np.zeros((len(data2),len(coln)))       
# arr1=np.array(data)                         #convert into matrix of data array
# 
# np.reshape(arrND, (-1,41))
# print arrND
# 
# """normalize the data in columns with continuous attributes"""                
# arr=np.zeros((len(data),len(coln)))
# 
# 
# for rows,i in itertools.izip(data,range(len(data))):
#     for col,j in itertools.izip(coln,range(len(coln))):
#         arr[i][j]=rows[col]
# 
# for rows,i in itertools.izip(data,range(len(data))):
#     for col,j in itertools.izip(coln,range(vL)):
#         arr1[i][j]=rows[col]
# 
# for rows,i in itertools.izip(data1,range(len(data1))):
#     for col,j in itertools.izip(coln,range(len(coln))):
#         arrN[i][j]=rows[col]
#         
#  
# for rows,i in itertools.izip(data2,range(len(data2))):
#     for col,j in itertools.izip(coln,range(len(coln))):
#         arrA[i][j]=rows[col]
# 
# 
# 
# #normalize the value in array
# rowz,colz=arrN.shape
# muN=np.zeros(colz)
# sdN=np.zeros(colz)
# muA=np.zeros(colz)
# sdA=np.zeros(colz)
# maxmN=np.zeros(colz)
# maxmA=np.zeros(colz)
# 
# "Mean,standard deviation for normal data"
# for i in range(len(coln)):
#     muN[i]=np.float64(np.mean(arrN[:,i]))
#     sdN[i]=np.float64(np.std(arrN[:,i]))
#     maxmN[i]=np.float64(np.max(arrN[:,i]))
# # for i in range(len(coln)):
# #     print i,sdN[i]   
# "Mean,standard deviation for anomaly data"
# 
# for i in range(len(coln)):
#     muA[i]=np.float64(np.mean(arrA[:,i]))
#     sdA[i]=np.float64(np.std(arrA[:,i]))
#     maxmA[i]=np.float64(np.max(arrA[:,i]))
#     
#     
# """ computation for continous probability"""
# # for rows in data:
# #      for counter in coln:
# #               conProbClass['col-'+str(counter),rows[len(rows)-1]]=round(np.exp(-np.square(x-mu[counter])/2*np.square(sd[counter])))/np.sqrt(2*np.pi*np.square(sd[counter]))
# 
# 
# """Normalize the array of data"""
# 
# for col in xrange(colz):
#     if arr[:,col].max()!=0:                             #avoiding the divide by zero for the column with zero value
#         arr[:,col] = arr[:,col]/abs(arr[:,col].max())
#         
# 
#          
# for rows,i in itertools.izip(data,range(len(data))):
#     for col,j in itertools.izip(coln,range(len(coln))):
#         rows[col]=arr[i][j]
#         if rows[col]<0.5:
#             rows[col]=0
#         else:
#             rows[col]=1
#            
# 
# # rw,cl=  arr1.shape
# # for col in xrange(cl):
# #     if is_number(arr1[1,col]) and (arr1[:,col].max())!=0:
# #         arr1[:,col]=arr1[:,col]/abs(arr1[:,col].max())
# 
# # for rows in arr1:
# #     print rows
# 
#  
"""Train the bayes_network"""            
for rows in data:
    for counter in range(len(rows)-1):
        if is_number(rows[counter]):
            continue
        else:
            predictCounts[rows[counter]]+=1                            # Count the number of normal and abnormal events with counter=len(rows), ie last column of table
for rows in data:
    if rows[len(rows)-1]=='normal.':
        predictCounts['Normal.']+=1
    else:
        predictCounts['Anomaly.']+=1             
 
for rows in data:
    for counter in range(len(rows)-1):
        if is_number(rows[counter]):
            continue
        elif rows[len(rows)-1]=='normal.':
            jointCount[rows[counter],'Normal.']+=1
        else:
            jointCount[rows[counter],'Anomaly.']+=1

"Compute the probability of normal and anomaly events"

probNE=[]                #probability of normal events
probAE=[]                #probability of anomaly events
np.float64(probNE)
np.float64(probAE)
probNE=round(predictCounts['Normal.'])/len(data)
probAE=round(predictCounts['Anomaly.'])/len(data)


           
# # for rows in arr1:
# # #     predictCounts[rows[len(rows)-1]]+=1
# #     for counter in range(len(rows)):
# #         if is_number(rows[counter]):
# #             if rows[counter]!=0:
# #                 predictCounts['col-'+str(counter),'1']+=1
# #                 jointCount['col-'+str(counter),'1',rows[(len(rows)-1)]]+=1
# #             else:
# #                 predictCounts['col'+str(counter),'0']=1
# #                 jointCount['col-'+str(counter),'0',rows[(len(rows)-1)]]=1
# # #             featureCounts['col-'+str(counter),rows[counter]]+=1
# # #         elif is_number(rows[counter]) and (rows[counter])<=1:
# # #             print l[counter]
# #         else:
# #             predictCounts[rows[counter]]+=1                            # Count the number of normal and abnormal events with counter=len(rows), ie last column of table
# #             columns['col-'+str(counter),rows[counter]]+=1
# #             featureCounts[('col-'+str(counter),rows[counter],rows[(len(rows)-1)])]+=1
# #             if counter!=(len(rows)-1):                              #excludes the column with attribute decision of normal or attack
# #                 jointCount[(rows[counter],rows[(len(rows)-1)])]+=1
# 
# 
# """Compute the probability values"""
#           
# # for key in columns:
# #     probClass[(key)]=round(columns[(key)])/round(len(data))
#     
#    
# """smoothing the data in table"""
# # for keys in predictCounts:
# #     if(predictCounts[(keys)]==0):
# #         predictCounts[(keys)]=1
# 
# # for rows in data:
# #     for counter in range(len(rows)-1):
# #         if is_number(rows[counter]):
# #             continue
# #         else:
# #             probClass[rows[counter]]=round(predictCounts[rows[counter]])/round(len(data))
# #             
# #             predictCounts[rows[counter]]+=1                            # Count the number of normal and abnormal events with counter=len(rows), ie last column of table
# #             columns['col-'+str(counter),rows[counter]]+=1
# #             featureCounts[('col-'+str(counter),rows[counter],rows[(len(rows)-1)])]+=1
# #             if counter!=(len(rows)-1):                              #excludes the column with attribute decision of normal or attack
# #                 jointCount[(rows[counter],rows[(len(rows)-1)])]+=1
# 
# 
"""Compute joint probability"""
for key in jointCount:
    for attr in ['Normal.','Anomaly.']:
        jointProbClass[(key)]=round(jointCount[(key)])/round(predictCounts[(attr)])
     
# 
#      
#         
# 
"""Predict the class for given new instance"""
 
normValN=[]
normValA=[]
normValN=np.zeros(len(coln))
normValA=np.zeros(len(coln))
 
newInstance=collections.defaultdict(int)
X=[]
# get the value of the instance
    
 
"""Classify the given instance"""
 
tst=open('c:\python27\dataTest.txt')
 
testVector=[]
probVectorN=np.zeros(len(coln))
probVectorA=np.zeros(len(coln))
# probN=[]
# probA=[]

probN=1
probA=1 
for line in tst:
    testVector.append(line.strip().strip('\n').split(','))
    break
#probVectorN=1
#probVectorA=1

np.float64(probVectorN)
np.float64(probVectorA) 

"Compute the probability of normal event given attributes"
i=0
for tv in testVector:
    for counter in coln:
        probVectorN[i] = np.float64(np.exp(-np.square(np.float64(tv[counter])-muN[i]))/2*np.square(stdN[i]))/np.sqrt(2*np.pi*np.square(stdN[i]))
        i+=1
         
i=0
for tv in testVector:
    for counter in coln:
        probVectorA[i] = np.float64(np.exp(-np.square(np.float64(tv[counter])-muA[i]))/2*np.square(stdA[i]))/np.sqrt(2*np.pi*np.square(stdA[i]))
        i+=1



for tv in testVector:
    for counter in range(len(tv)):
        if is_number(tv[counter]):
            continue
        else:
            probN*=jointProbClass[(tv[counter],'Normal.')]
            probA*=jointProbClass[(tv[counter],'Anomaly.')]

for i in probVectorN:
    probN*=i
probN*=probNE                           #multiplied by the probability of normal event
   
for j in probVectorA:
    probA*=j
probA*=probAE                           #multiplied by the probability of anomaly event
"Predict the class for the given instance"
if probN>probA:
    print "The given activity is Normal"
else:
    print "Intrusion has been observed" 

# 
# for tv in testVector:
#     for counter in range(len(tv)):
#         if is_number(tv[counter]):
#             continue
#         else:
#             probN.append(jointProbClass[(tv[counter],'Normal.')])
#          
# for tv in testVector:
#     for counter in range(len(tv)):
#         if is_number(tv[counter]):
#             continue
#         else:
#             probN.append(jointProbClass[(tv[counter],'Normal.')])        
#              
#              
# j=0            
# for tv in testVector:
#     for counter in coln:
#         probVectorA.append(round(np.exp(np.negative(np.square(np.float64(tv[counter])-muA[j]))/2*np.square(sdA[j])))/np.sqrt(2*np.pi*np.square(sdA[j])))
#         j+=1
#          
# for tv in testVector:
#     for counter in range(len(tv)):
#         if is_number(tv[counter]):
#             continue        
#         else:
#             probA.append(jointProbClass[(tv[counter],'Anomaly.')])
#              
#  
#                   
